﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace FDEE.Model
{
   
   public  static class GlobalFuncs
    {
        /// <summary>
        /// 根据钢束类别获取单重.
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static double GetUnitWeight(eStrandClass pt)
        {
            switch (pt)
            {
                case eStrandClass.S152:
                    return 1.102;                    
                default:
                    return 0.0;
            }
        }

        public static double GetStrandArea(eStrandClass strandsType)
        {
            switch (strandsType)
            {
                case eStrandClass.S152:
                    return 140;
                default:
                    return 0.0;
            }
        }

        /// <summary>
        /// 根据钢筋直径获取单重.
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static double GetUnitWeight(eDB d)
        {
            switch (d)
            {
                case eDB.None:
                    throw (new Exception("钢筋直径错误."));
                // break;
                case eDB.DB10:
                    return 0.617;
                case eDB.DB12:
                    return 0.888;
                case eDB.DB16:
                    return 1.552;
                    //return 1.578;
                case eDB.DB20:
                    return 2.466;
                case eDB.DB22:
                    return 2.980;
                case eDB.DB25:
                    return 3.973;
                    //return 3.853;
                case eDB.DB28:
                    return 4.830;
                    //return 4.834;
                case eDB.DB32:
                    return 6.404;
                default:
                    return 0.0;
            }
        }
        /// <summary>
        /// 根据相应钢筋类别计算长度
        /// </summary>
        /// <param name="st"></param>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="C"></param>
        /// <param name="D"></param>
        /// <param name="Lx"></param>
        /// <returns></returns>
        public static Tuple<string, int> GetFormulaLength(eShapeType st, double A = 0, double B = 0, double C = 0, double D = 0, int Lx = 0)
        {
            switch (st)
            {
                case eShapeType.None:
                    throw (new Exception("钢筋直径错误."));
                // break;
                case eShapeType.StABCD:
                    return new Tuple<string, int>("L=2A+B+2C+D+Lx", (int)(2 * A + B + 2 * C + D) + Lx);
                case eShapeType.Pile1a:
                    return new Tuple<string, int>("L=", (int)A);
                case eShapeType.MY:
                    return new Tuple<string, int>("L=", (int)A);
                default:
                    return null;
            }
        }
        public static double GetDevLength(eConcreteClass c, eDB d)
        { 
         if (c == eConcreteClass.C30)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 900;
                    case eDB.DB28:
                        return 1130;
                    case eDB.DB32:
                        return 1470;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C35)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 830;
                    case eDB.DB28:
                        return 1050;
                    case eDB.DB32:
                        return 1360;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C45)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 750;
                    case eDB.DB28:
                        return 920;
                    case eDB.DB32:
                        return 1200;
                    default:
                        return 0;
                }
            }

            else
            {
                throw (new Exception("混凝土强度错误"));
            }
        }

        public static double GetLapLength(eConcreteClass c, eDB d)
        {
            if (c == eConcreteClass.C30)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 1170;
                    case eDB.DB28:
                        return 1470;
                    case eDB.DB32:
                        return 1900;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C35)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 1080;
                    case eDB.DB28:
                        return 1360;
                    case eDB.DB32:
                        return 1770;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C45)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 980;
                    case eDB.DB28:
                        return 1200;
                    case eDB.DB32:
                        return 1560;
                    default:
                        return 0;
                }
            }

            else
            {
                throw (new Exception("混凝土强度错误"));
            }
        }

        /// <summary>
        /// 根据钢筋直径输出相应弯钩尺寸，对应h\n\Lx
        /// </summary>
        /// <param name="d"></param>
        /// <param name="angle">90°弯钩、180°弯钩、360°为箍筋stirrup</param>
        /// <returns></returns>
        public static double GetHookLength(eDB d, double angle)
        {
            if (angle == 90)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 550;
                    case eDB.DB28:
                        return 480;
                    case eDB.DB25:
                        return 400;
                    case eDB.DB20:
                        return 320;
                    case eDB.DB16:
                        return 256;
                    case eDB.DB12:
                        return 192;
                    case eDB.DB10:
                        return 160;
                    default:
                        return 0;
                }
            }
            else if (angle == 180)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 410;
                    case eDB.DB28:
                        return 370;
                    case eDB.DB25:
                        return 280;
                    case eDB.DB20:
                        return 220;
                    case eDB.DB16:
                        return 180;
                    case eDB.DB12:
                        return 155;
                    case eDB.DB10:
                        return 140;
                    default:
                        return 0;
                }
            }
            else if (angle == 360)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 870;
                    case eDB.DB28:
                        return 770;
                    case eDB.DB25:
                        return 690;
                    case eDB.DB20:
                        return 550;
                    case eDB.DB16:
                        return 256;
                    case eDB.DB12:
                        return 192;
                    case eDB.DB10:
                        return 170;
                    default:
                        return 0;
                }
            }
            else if (angle == 135)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));                
                    case eDB.DB16:
                        return 190;
                    case eDB.DB12:
                        return 150;                
                    default:
                        return 0;
                }
            }
            else
            {
                throw (new Exception("弯钩角度输入错误，应为90/135/180/360"));
            }
        }

        public static double GetR(eDB d, double angle)
        {
            if (angle == 90)
            {
                if (d == eDB.DB32 || d == eDB.DB28)
                {
                    return 4 * Convert.ToInt32(d);
                }
                else
                {
                    return 3 * Convert.ToInt32(d);
                }

            }
            else if (angle == 360)
            {
                if (Convert.ToInt32(d) >= 20)
                {
                    return 3 * Convert.ToInt32(d);
                }
                else
                {
                    return 2 * Convert.ToInt32(d);
                }
            }
            else
            {
                throw (new Exception("弯钩角度输入错误，应为90/360"));
            }
        }

        /// <summary>
        /// 获取螺旋筋长度
        /// </summary>
        /// <param name="H">高度</param>
        /// <param name="dia">螺旋筋自身直径</param>
        /// <param name="spacingL">螺旋筋间距</param>
        /// <param name="pileDia">桩径</param>
        /// <returns></returns>
        public static double GetSpiralLength(double H,int dia,double spacingL,double pileDia=1000,double cover=75)
        {
            double innerDia = pileDia - 2 * cover - 2 * dia;        
            double length = 0;
            double value = (Math.Pow(Math.PI * (innerDia+dia), 2)) + spacingL;
            //H = 1000;
            length = ((1000/spacingL)*Math.Sqrt(Math.Pow(Math.PI * (innerDia + dia), 2)+spacingL) + Math.PI * dia * 0.5)*0.001;
           // length =Math.Round(((1000 / spacingL) * Math.Pow(value, 0.5)+Math.PI*dia*0.5)*0.001,3,MidpointRounding.AwayFromZero);
            return length;
        }
/*        public static double GetSpiralLength(double H, int dia, double spacingL, double pileDia = 1000, double cover = 75)
        {
            double innerDia = pileDia - 2 * cover - 2 * dia;
            double length = 0;
            double value = (Math.Pow(Math.PI * (innerDia + dia), 2)) + Math.Pow(spacingL, 2);
            //H = 1000;
            length = Math.Round(((H / spacingL) * Math.Pow(value, 0.5)) * 0.001, 3, MidpointRounding.AwayFromZero);
            return length;
        }*/

       /// <summary>
       /// 取最近的5或10倍数
       /// </summary>
       /// <param name="f"></param>
       /// <returns></returns>
        public static double transmit5o10Num(double f)
        {
            f = f * 0.1;
            if ((f - (int)f) <= 0.5 && (f - (int)f > 0))
                return ((int)f + 0.5) * 10;
            if ((f - (int)f) > 0.5)
                return ((int)f + 1.0) * 10;
            if ((f - (int)f) == 0)
                return f * 10;
            return f*10;
        }

        /// <summary>
        /// 取较大的最近的10倍数
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static double transmit10Num(double f)
        {
            f = f * 0.1;
            if ((f - (int)f > 0))
                return ((int)f + 1.0) * 10;
            if ((f - (int)f) == 0)
                return f * 10;
            return f * 10;
        }

        /// <summary>
        /// 大于零进一
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static double transmitNum(double f)
        {         
            if ((f - (int)f > 0))
                return (int)f + 1 ;
            else
                return (int)f;

        }


        /// <summary>
        /// 对一组点通过最小二乘法进行线性回归
        /// </summary>
        /// <param name="parray"></param>
        public static void LinearRegression(Vector2[] parray,out double k,out double b,out double err)
        {
            //点数不能小于2
            if (parray.Length < 2)
            {
                throw new Exception();
            }
            //求出横纵坐标的平均值
            double averagex = 0, averagey = 0;
            foreach (Vector2 p in parray)
            {
                averagex += p.X;
                averagey += p.Y;
            }
            averagex /= parray.Length;
            averagey /= parray.Length;
            //经验回归系数的分子与分母
            double numerator = 0;
            double denominator = 0;
            foreach (Vector2 p in parray)
            {
                numerator += (p.X - averagex) * (p.Y - averagey);
                denominator += (p.X - averagex) * (p.X - averagex);
            }
            //回归系数b（Regression Coefficient）
            double RCB = numerator / denominator;
            //回归系数a
            double RCA = averagey - RCB * averagex;
            k = RCB;
            b = RCA;
            //Console.WriteLine("回归系数A： " + RCA.ToString("0.0000"));
            //Console.WriteLine("回归系数B： " + RCB.ToString("0.0000"));
            //Console.WriteLine(string.Format("方程为： y = {0} + {1} * x", RCA.ToString("0.0000"), RCB.ToString("0.0000")));
            //剩余平方和与回归平方和
            double residualSS = 0;  //（Residual Sum of Squares）
            double regressionSS = 0; //（Regression Sum of Squares）
            foreach (Vector2 p in parray)
            {
                residualSS +=
                  (p.Y - RCA - RCB * p.X) *
                  (p.Y - RCA - RCB * p.X);
                regressionSS +=
                  (RCA + RCB * p.X - averagey) *
                  (RCA + RCB * p.X - averagey);
            }
            err = residualSS;
            //Console.WriteLine("剩余平方和： " + residualSS.ToString("0.0000"));
            //Console.WriteLine("回归平方和： " + regressionSS.ToString("0.0000"));
        }




    }

}
